package com.jindy.module.drawBill.service.impl;

import com.jindy.common.constant.Constants;
import com.jindy.common.core.domain.AjaxResult;
import com.jindy.common.core.domain.model.LoginUser;
import com.jindy.common.exception.base.BaseException;
import com.jindy.common.utils.DateUtils;
import com.jindy.common.utils.SecurityUtils;
import com.jindy.common.utils.StringUtils;
import com.jindy.jpush.utils.UniJpushUtils;
import com.jindy.module.approvalConfig.domain.ApprovalConfig;
import com.jindy.module.approvalConfig.mapper.ApprovalConfigMapper;
import com.jindy.module.approvalRecord.domain.ApprovalRecord;
import com.jindy.module.approvalRecord.mapper.ApprovalRecordMapper;
import com.jindy.module.drawBill.domain.DrawBill;
import com.jindy.module.drawBill.domain.DrawBillSearch;
import com.jindy.module.drawBill.domain.DrawBillSearchResult;
import com.jindy.module.drawBill.mapper.DrawBillMapper;
import com.jindy.module.drawBill.service.IDrawBillService;
import com.jindy.module.drawBillDetail.domain.DrawBillDetail;
import com.jindy.module.drawBillDetail.mapper.DrawBillDetailMapper;
import com.jindy.module.jpush.mapper.JpushMapper;
import com.jindy.module.order.domain.Order;
import com.jindy.module.order.mapper.OrderMapper;
import com.jindy.module.serialNum.service.ISySerialNumTService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 开票申请Service业务层处理
 * 
 * @author yu
 * @date 2023-05-17
 */
@Service
public class DrawBillServiceImpl implements IDrawBillService 
{
    private static final Logger LOGGER = LoggerFactory.getLogger(DrawBillServiceImpl.class);
    @Resource
    private DrawBillMapper drawBillMapper;

    /**
     * 审批记录
     */
    @Resource
    private ApprovalRecordMapper approvalRecordMapper;

    /**
     * 审批记录配置信息
     */
    @Resource
    private ApprovalConfigMapper approvalConfigMapper;

    /**
     * 设备id配置表
     */
    @Resource
    private JpushMapper jpushMapper;

    /**
     * 开票明细
     */
    @Resource
    private DrawBillDetailMapper drawBillDetailMapper;

    /**
     * 生成流水单号Service
     */
    @Resource
    private ISySerialNumTService serialNumTService;

    /**
     * 订单Mapper
     */
    @Resource
    private OrderMapper orderMapper;



    /**
     * 查询开票申请
     * 
     * @param id 开票申请主键
     * @return 开票申请
     */
    @Override
    public DrawBill selectDrawBillById(Long id)
    {
        return drawBillMapper.selectDrawBillById(id);
    }

    /**
     * 查询开票申请列表
     * 
     * @param drawBill 开票申请
     * @return 开票申请
     */
    @Override
    public List<DrawBill> selectDrawBillList(DrawBill drawBill)
    {
        return drawBillMapper.selectDrawBillAndDetailList(drawBill);
    }

    /**
     * 新增开票申请
     * 
     * @param drawBill 开票申请
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void insertDrawBill(DrawBill drawBill)
    {
        // 获取当前人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请先登录");
        }
        int flag = BigDecimal.ZERO.compareTo(drawBill.getAbleBillAmount());
        if (flag > 0){
            throw new BaseException("可开票金额为0，不可申请");
        }
        // 判断是否再提交
        if (null==drawBill.getId()){
            // 生成流水单号
            String serialNum = serialNumTService.generateSerialNum("KPSQ");
            if (StringUtils.isBlank(serialNum)) {
                throw new BaseException("新增开票申请审批-获取开票申请单号失败");
            }
            drawBill.setSerialNum(serialNum);
            drawBill.setCreateTime(DateUtils.getNowDate());
            drawBillMapper.insertDrawBill(drawBill);
            //新增开票明细
            if (!CollectionUtils.isEmpty(drawBill.getDrawBillDetailList())){
                addDrawBillDetail(drawBill, loginUser);
            }
        }else{
            drawBill.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
            drawBill.setUpdateBy(loginUser.getUsername());
            updateDrawBill(drawBill);
            //删除审批记录
            approvalRecordMapper.deleteApprovalRecordBySerialNum(drawBill.getSerialNum());
        }
        // 新增审批记录
        List<Long> addJpushList= addApprovalRecord(drawBill);
        sendApproveMessage(addJpushList);
    }

    /**
     * 新增开票明细
     * @param drawBill
     * @param loginUser
     */
    @Transactional(rollbackFor = Exception.class)
    public void addDrawBillDetail(DrawBill drawBill, LoginUser loginUser) {
        List<DrawBillDetail> drawBillDetails = new ArrayList<>();
        for (DrawBillDetail drawBillDetail : drawBill.getDrawBillDetailList()) {
            drawBillDetail.setSerialNum(drawBill.getSerialNum());
            drawBillDetail.setCreateTime(DateUtils.getNowDate());
            drawBillDetail.setCreateBy(loginUser.getUsername());
            drawBillDetails.add(drawBillDetail);
        }
        drawBillDetailMapper.insertBathDrawBillDetail(drawBillDetails);
    }

    /**
     * 给审批人推送消息
     * @param addJpushList
     */
    private void sendApproveMessage(List<Long> addJpushList) {
        try {
            List<String> addRegIds = jpushMapper.selectRegistrationIdsByUserIds(addJpushList);
            if (!CollectionUtils.isEmpty(addRegIds)){
                UniJpushUtils.sendApproveMessage(addRegIds);
            }
        } catch (Exception e) {
            LOGGER.error("开票申请审批人推送通知失败",e);
        }
    }

    /**
     * 添加审批流程记录
     *
     * @param drawBill
     */
    @Transactional(rollbackFor = Exception.class)
    public List<Long> addApprovalRecord(DrawBill drawBill) {
        // 消息推送人员
        List<Long> jpushList = new ArrayList<>();
        int sequence = 1;
        //  发起人
        ApprovalRecord firstApprovalRecord = getApprovalRecord(drawBill);
        firstApprovalRecord.setSequence(sequence);
        firstApprovalRecord.setApprovalStatus(Constants.COMPLETED);
        firstApprovalRecord.setTypeOperation(Constants.AGREE);
        firstApprovalRecord.setBusinessStatus(Constants.APPROVE);
        firstApprovalRecord.setApproverId(Long.valueOf(drawBill.getApplyUserId()));
        firstApprovalRecord.setApproverName(drawBill.getApplyUserName());
        approvalRecordMapper.insertApprovalRecord(firstApprovalRecord);

        sequence++;
        //  默认周总
        List<ApprovalConfig> approvalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("KQSQ_DEPT_LEADER", "1"));
        if (CollectionUtils.isEmpty(approvalConfigList)) {
            throw new RuntimeException("请检查审批配置信息：KQSQ_DEPT_LEADER");
        }
        jpushList.add(approvalConfigList.get(0).getUserId());
        addApprovalConfig(sequence, approvalConfigList,drawBill);

        sequence++;
        //  财务领导
        List<ApprovalConfig> thirdApprovalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("KQSQ_CW_LEADER", "1"));
        if (CollectionUtils.isEmpty(thirdApprovalConfigList)) {
            throw new RuntimeException("请检查审批配置信息：KQSQ_CW_LEADER");
        }
        addApprovalConfig(sequence, thirdApprovalConfigList,drawBill);

        sequence++;
        //  财务领导
        List<ApprovalConfig> fourApprovalConfigList = approvalConfigMapper.selectApprovalConfigList(new ApprovalConfig("KQSQ_KP_STAFF", "1"));
        if (CollectionUtils.isEmpty(thirdApprovalConfigList)) {
            throw new RuntimeException("请检查审批配置信息：KQSQ_KP_STAFF");
        }
        addApprovalConfig(sequence, fourApprovalConfigList,drawBill);
        return jpushList;
    }

    /**
     * 新增第二，第三审批记录信息
     *
     * @param sequence
     * @param approvalConfigList
     */
    @Transactional(rollbackFor = Exception.class)
    public void addApprovalConfig(int sequence, List<ApprovalConfig> approvalConfigList,DrawBill drawBill) {
        String status = Constants.NOT_APPROVED;
        if (sequence == 2) {
            status = Constants.APPROVE;
        }
        for (ApprovalConfig approvalConfig : approvalConfigList) {
            ApprovalRecord approvalRecord = getApprovalRecord(drawBill);
            approvalRecord.setSequence(sequence);
            approvalRecord.setApprovalStatus(status);
            approvalRecord.setApproverId(approvalConfig.getUserId());
            approvalRecord.setApproverName(approvalConfig.getUsername());
            approvalRecordMapper.insertApprovalRecord(approvalRecord);
        }
    }

    /**
     * 获取审批记录对象
     *
     * @param drawBill
     * @return
     */
    private ApprovalRecord getApprovalRecord(DrawBill drawBill) {
        ApprovalRecord approvalRecord = new ApprovalRecord();
        approvalRecord.setSerialNum(drawBill.getSerialNum());
        approvalRecord.setUserId(Long.valueOf(drawBill.getApplyUserId()));
        approvalRecord.setOrderId(drawBill.getId());
        approvalRecord.setUserName(drawBill.getApplyUserName());
        approvalRecord.setUpdateTime(DateUtils.parseDate(DateUtils.getTime()));
        approvalRecord.setUpdateBy(drawBill.getApplyUserName());
        approvalRecord.setCreateBy(drawBill.getApplyUserName());
        approvalRecord.setCreateTime(DateUtils.parseDate(DateUtils.getTime()));
        return approvalRecord;
    }

    /**
     * 修改开票申请
     * 
     * @param drawBill 开票申请
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateDrawBill(DrawBill drawBill)
    {
        // 获取当前人
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null) {
            throw new RuntimeException("请先登录");
        }
        //删除开票明细
        drawBillDetailMapper.deleteDrawBillDetailBySerialNum(drawBill.getSettleNum());
        //新增开票明细
        if (!CollectionUtils.isEmpty(drawBill.getDrawBillDetailList())){
            addDrawBillDetail(drawBill, loginUser);
        }
        drawBill.setUpdateTime(DateUtils.getNowDate());
        return drawBillMapper.updateDrawBill(drawBill);
    }

    /**
     * 批量删除开票申请
     * 
     * @param ids 需要删除的开票申请主键
     * @return 结果
     */
    @Override
    public int deleteDrawBillByIds(Long[] ids)
    {
        return drawBillMapper.deleteDrawBillByIds(ids);
    }

    /**
     * 删除开票申请信息
     * 
     * @param id 开票申请主键
     * @return 结果
     */
    @Override
    public int deleteDrawBillById(Long id)
    {
        return drawBillMapper.deleteDrawBillById(id);
    }

    /**
     * 获取开票申请信息
     * @param drawBillSearch
     * @return
     */
    @Override
    public AjaxResult getSettlement(DrawBillSearch drawBillSearch) {
        //获取已完成对账单
        if ("1".equals(drawBillSearch.getOrderType())){
            //租赁订单
            return AjaxResult.success(drawBillMapper.getSettlementOrder(drawBillSearch));
        }else{
            List<DrawBillSearchResult> list = new ArrayList<>();
            //销售订单
            Order order = new Order();
            order.setContractTemplate("2");
            List<Order> orders = orderMapper.selectOrderList(order);
            if (CollectionUtils.isEmpty(orders)){
                return AjaxResult.success(list);
            }
            for (Order o : orders) {
                DrawBillSearchResult drawBillSearchResult = new DrawBillSearchResult();
                drawBillSearchResult.setProjectName(o.getProjectName());
                drawBillSearchResult.setCustomerId(String.valueOf(o.getCustomerId()));
                drawBillSearchResult.setCustomerName(o.getCustomerName());
                drawBillSearchResult.setNumber(o.getOrderNo());
                drawBillSearchResult.setPayAmount(o.getReceivedAmount());
                list.add(drawBillSearchResult);
            }
            return AjaxResult.success(list);
        }

    }

    /**
     * 获取可结算余额
     * @param serialNum
     * @return
     */
    @Override
    public AjaxResult getAblePayAmount(String serialNum) {
        if (serialNum.contains("DZ")){
            //获取结算单
            DrawBillSearch drawBillSearch = new DrawBillSearch();
            drawBillSearch.setNumber(serialNum);
            List<DrawBillSearchResult> orderList = drawBillMapper.getSettlementOrder(drawBillSearch);
            if (CollectionUtils.isEmpty(orderList)){
                throw new BaseException("没有找到该结算单");
            }
            List<DrawBill> drawBills = drawBillMapper.getAblePayAmount(serialNum);
            if (CollectionUtils.isEmpty(drawBills)){
                return AjaxResult.success(orderList.get(0).getPayAmount());
            }else{
                //获取已开票得金额
                BigDecimal sum = drawBills.stream().map(DrawBill::getBillTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                return AjaxResult.success(orderList.get(0).getPayAmount().subtract(sum));
            }
        }else{
            Order order = new Order();
            order.setOrderNo(serialNum);
            List<Order> orders = orderMapper.selectOrderList(order);
            if (CollectionUtils.isEmpty(orders)){
                throw new BaseException("没有找到该销售订单");
            }
            List<DrawBill> drawBills = drawBillMapper.getAblePayAmount(serialNum);
            if (CollectionUtils.isEmpty(drawBills)){
                return AjaxResult.success(orders.get(0).getReceivedAmount());
            }else{
                //获取已开票得金额
                BigDecimal sum = drawBills.stream().map(DrawBill::getBillTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                return AjaxResult.success(orders.get(0).getReceivedAmount().subtract(sum));
            }
        }

    }
}
